// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.repo

import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import xyz.apiote.bimba.czwek.api.getTransitousDepartures
import xyz.apiote.bimba.czwek.api.responses.DeparturesResponse
import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseDev
import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseV1
import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseV2
import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseV3
import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseV4
import xyz.apiote.bimba.czwek.api.responses.ErrorResponse
import xyz.apiote.bimba.czwek.api.responses.LineResponse
import xyz.apiote.bimba.czwek.api.responses.LineResponseDev
import xyz.apiote.bimba.czwek.api.responses.LineResponseV1
import xyz.apiote.bimba.czwek.api.responses.LineResponseV2
import xyz.apiote.bimba.czwek.api.responses.LineResponseV3
import xyz.apiote.bimba.czwek.data.sources.Server
import java.time.LocalDate

// todo [3.2] in Repository check if responses are BARE or HTML

class OnlineRepository {
	 suspend fun getDepartures(
		feedID: String,
		stop: String,
		date: LocalDate?,
		context: Context,
		limit: Int?,
		exact: Boolean
	): StopEvents? {
		return if (feedID == "transitous") {
			getTransitousDepartures(context, stop, date, limit, exact)
		} else {
			val result = xyz.apiote.bimba.czwek.api.getDepartures(
				context,
				Server.get(context),
				feedID,
				stop,
				date,
				limit
			)

			if (result.error != null) {
				if (result.stream != null) {
					val response = withContext(Dispatchers.IO) { ErrorResponse.unmarshal(result.stream) }
					throw TrafficResponseException(result.error.statusCode, response.message, result.error)
				} else {
					throw TrafficResponseException(result.error.statusCode, "", result.error)
				}
			} else {
				when (val response =
					withContext(Dispatchers.IO) { DeparturesResponse.unmarshal(result.stream!!) }) {
					is DeparturesResponseDev -> StopEvents(
						response.departures.map { Event(it) },
						Stop(response.stop),
						response.alerts.map { Alert(it) })

					is DeparturesResponseV4 -> StopEvents(
						response.departures.map { Event(it) },
						Stop(response.stop),
						response.alerts.map { Alert(it) })

					is DeparturesResponseV3 -> StopEvents(
						response.departures.map { Event(it) },
						Stop(response.stop),
						response.alerts.map { Alert(it) })

					is DeparturesResponseV2 -> StopEvents(
						response.departures.map { Event(it) },
						Stop(response.stop),
						response.alerts.map { Alert(it) })

					is DeparturesResponseV1 -> StopEvents(
						response.departures.map { Event(it) },
						Stop(response.stop),
						response.alerts.map { Alert(it) })

					else -> null
				}
			}
		}
	}

	 suspend fun getLine(
		context: Context, feedID: String, lineName: String, lineID: String
	): Line? {
		val result =
			xyz.apiote.bimba.czwek.api.getLine(context, Server.get(context), feedID, lineName, lineID)
		if (result.error != null) {
			if (result.stream != null) {
				val response = withContext(Dispatchers.IO) { ErrorResponse.unmarshal(result.stream) }
				throw TrafficResponseException(result.error.statusCode, response.message, result.error)
			} else {
				throw TrafficResponseException(result.error.statusCode, "", result.error)
			}
		} else {
			return when (val response =
				withContext(Dispatchers.IO) { LineResponse.unmarshal(result.stream!!) }) {
				is LineResponseDev -> Line(response.line)
				is LineResponseV1 -> Line(response.line)
				is LineResponseV2 -> Line(response.line)
				is LineResponseV3 -> Line(response.line)
				else -> null
			}
		}
	}
}
